<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<link rel="stylesheet" type="text/css" href="/resources/ace/css/cacheCloud-self.css"/>
<link rel="stylesheet" type="text/css" href="/resources/ace/css/cacheCloud-appCommand.css"/>
<div class="row command mt20">
    <input type="hidden" id="appId" value="${appId}">
    <div class="col-md-4">
        <div class="command-form">
            <div class="row">
                <div class="col-md-8">
                    <c:if test="${appDesc.type eq 2}">
                        <input type="text" class="form-control" value="Redis-Cluster" disabled>
                    </c:if>
                    <c:if test="${appDesc.type eq 5}">
                        <input type="text" class="form-control" value="Redis-Sentinel" disabled>
                    </c:if>
                    <c:if test="${appDesc.type eq 6}">
                        <input type="text" class="form-control" value="Redis-standalone" disabled>
                    </c:if>

                </div>
                <c:if test="${userInfo.type != 2}">
                    <div class="col-md-4">
                        <button class="btn btn-info fr" id="addKeyBtn">新增Key</button>
                    </div>
                </c:if>

            </div>
            <div class="row mt20">
                <div class="col-md-12">
                    <input type="text" placeholder="请填写key" name="redisKey" class="form-control" />
                </div>
            </div>
            <div class="row" style="margin-top: 5px;">
                <div class="col-md-12" style="text-align: right;">
                    <label>
                        <input type="checkbox" name="accurate">
                         &nbsp;精确查找
                    </label>
                    <button class="btn btn-default ml20" id="searchTree">搜索</button>
                </div>
            </div>
        </div>
        <div class="comand-list mt20">
            <div class="customFile" id="customFile">
            </div>
            <div class="load">
                <div class="load-more mt20">
                    <div id="treeLoadMore">加载更多</div>
                </div>
                <div class="load-more mt20">
                    <div id="treeLoadAll">加载所有</div>
                </div>
            </div>
        </div>
    </div>
    <div class="col-md-8 bl">
        <div class="row">
            <div class="col-md-4">
                <label id="redisTypeName">List : </label>
                <input type="text" class="form-control dib w180">
            </div>
            <div class="col-md-4">
                <label>TTL : </label>
                <input id="TTL" type="text" class="form-control dib w180">
            </div>
            <div class="col-md-4">
                <c:if test="${userInfo.type != 2}">
                    <button class="btn btn-default" id="saveTTL">设置时间</button>
                    <button class="btn btn-danger fr" id="delBtn">删除</button>
                </c:if>
                <button class="btn btn-info fr" id="refreshBtn">刷新</button>
            </div>
        </div>
        <!-- LHSZ: list hash set zset -->
        <div class="list" id="LHSZ">
            <c:if test="${userInfo.type != 2}">
                <div class="row mt20">
                    <div class="col-md-12">
                        <button class="btn btn-info" id="addBtn">添加</button>
                    </div>
                </div>
            </c:if>

            <div class="row">
                <div class="col-md-12">
                    <table class="table-hover cache-table">
                        <thead>
                        </thead>
                        <tbody>
                        </tbody>
                    </table>
                    <div class="load-more mt20">
                        <div>加载更多</div>
                    </div>
                </div>
            </div>
        </div>
        <div class="string" id="redisString"  style="display: none;">
            <div class="row mt20">
                <div class="col-md-12">
                    <textarea class="cacheCloud-textarea" name="" id="stringInput" rows="10"></textarea>
                    <c:if test="${userInfo.type != 2}">
                        <button class="btn btn-info mt20" id="stringSave">保存</button>
                    </c:if>
                </div>
            </div>
        </div>
    </div>
</div>
<div class="editDialog" id="editDialog" style="z-index: 10">
    <div class="editDialog-con">
        <c:if test="${userInfo.type != 2}">
            <div class="editDialog-con-title">
                <span>新增 / 编辑</span>
            </div>
        </c:if>
        <div class="editDialog-con-form">
            <div class="form-item" id="dialogInput">
                <p>Filed</p>
                <input type="text" class="cacheCloud-input">
            </div>
            <div class="form-item">
                <p>value</p>
                <textarea class="cacheCloud-textarea" name="" id="formValue" rows="10"></textarea>
            </div>
        </div>
        <c:if test="${userInfo.type != 2}">
            <div class="editDialog-con-btns">
                <div></div>
                <div>
                    <button class="btn btn-default" id="closeEditDialog">取消</button>
                    <button class="btn btn-info" id="saveEditDialog">保存</button>
                </div>
            </div>
        </c:if>

    </div>
</div>
<div class="editDialog" id="addKeyDialog" style="z-index: 1">
    <div class="editDialog-con">
        <c:if test="${userInfo.type != 2}">
            <div class="editDialog-con-title">
                <span>新增Key</span>
            </div>
        </c:if>
        <div class="editDialog-con-form">
            <div class="form-item">
                <p>键名</p>
                <textarea class="cacheCloud-textarea" name="" id="addKeyValue" rows="10"></textarea>
            </div>
            <div class="form-item">
                <p>类型</p>
                <select id="addKeyTypeSelect" class="form-control">
                    <option value="list">list</option>
                    <option value="set">set</option>
                    <option value="hash">hash</option>
                    <option value="string">string</option>
                    <option value="zset">zset</option>
                </select>
            </div>
        </div>
        <div class="editDialog-con-btns">
            <div></div>
            <c:if test="${userInfo.type != 2}">
                <div>
                    <button class="btn btn-default" id="addKeyCancel">取消</button>
                    <button class="btn btn-info" id="addKeySave">保存</button>
                </div>
            </c:if>

        </div>
    </div>
</div>

<div class="message" id="message">
    <p>操作成功</p>
</div>

<script src="/resources/ace/js/itools.js"></script>

<script>
    (function() {
        $(document).ready(function () {
            var ipPortReg = /(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\:(6553[0-5]|655[0-2]\d|65[0-4]\d{2}|6[0-4]\d{3}|[0-5]\d{4}|[1-9]\d{0,3})/;
            var tableTheadOptions = {
                list: ["ID", "Value", "Operation"],
                hash: ["ID", "Key", "Value", "search"],
                set: ["ID", "Value", "Search"],
                zset: ["ID", "Score", "Member", "Search"]
            };
            var treeAll = {};
            var treeCurrPage = 0;
            var treeCurrSize = 50;
            var treeSearchValue = "*";
            // 刷新树
            var refreshTree = true;
            var redisTypeName = $("#redisTypeName");
            var redisLHSZ = $("#LHSZ");
            var currTreeItemKey = "";
            var currType = "";
            var treeHtml = "";
            var tableCurrIndex = -1;
            var currRowValue = "";
            var currRowInput = "";
            var messageTimer = null;

            function commands(dos, cb) { // 发送命令
                $.ajax({
                    url: "/admin/app/commandExecute.json",
                    data: {appId: $('#appId').val(), command: dos},
                    dataType: "json",
                    success: function (res) {
                        cb && cb(res)
                    }
                });
            }

            function getTree(dos, resetCurrPage) {
                treeHtml = "";
                dos = dos || "scan "+ treeCurrPage +" MATCH " + treeSearchValue + " COUNT " + treeCurrSize;
                commands(dos, function(res) {
                    if(dos.includes("exists")) {
                        if(res.result == "1") {
                            var s = dos.split(" ")[1].trim();
                            drawTree(initData("\r\n" + s, resetCurrPage))
                        } else drawTree(null)
                    } else {
                        drawTree(initData(res.result, resetCurrPage))
                    }
                });
            }

            getTree();

            function msgShow(str) {
                str = str || "操作成功"
                var message = $("#message");
                clearTimeout(messageTimer);
                messageTimer = setTimeout(function() {
                    message.removeClass("message_show");
                }, 2000)
                message.addClass("message_show").find("p").html(str);
            }

            function initData(data, resetCurrPage) { // 初始化数据
                data = data || "";
                var arr = data.split(/[(\r\n)|\n]/g);
                var res = {};
                var sliceIndex = 1;
                var appDescType = "${appDesc.type}";

                if(appDescType == 2) {
                    sliceIndex = 1;
                } else if(appDescType == 5 || appDescType == 6) {
                    sliceIndex = 0;
                }

                if(refreshTree) {
                    treeAll = {};
                }

                arr = arr.slice(sliceIndex, arr.length);
                function fmtItem(curr, list, source, endStr) {
                    var first = list.shift();
                    
                    if(!first) return;
                    if(!curr[first]) {
                        if(source.indexOf(first) < source.length - 1) {
                            curr[first] = {};
                        }
                    }

                    fmtItem(curr[first], list, source, endStr);

                    if(source.indexOf(first) == source.length - 1) {
                        curr[endStr] = endStr;
                    }
                }
                
                if(appDescType == 5 || appDescType == 6) {
                    treeCurrPage = arr.slice(0, 1)[0] || 0;
                    arr.shift();
                }
                for(var i = 0; i < arr.length; i++) {
                    if(!arr[i] || ipPortReg.test(arr[i])) {
                        var a = arr[i].split(":");
                        var pageNo = a[a.length - 1].trim();
                        pageNo && (treeCurrPage = pageNo);
                        continue;
                    }
                    if(!arr[i].includes(":")) res[arr[i]] = arr[i];
                    else {
                        var list = arr[i].split(":");
                        fmtItem(res, list, list.slice(), arr[i])
                    }
                }
                if(resetCurrPage) treeAll = res;
                else Object.assign(treeAll, res);
                if(treeCurrPage == 0) {
                    $("#treeLoadMore").css("cursor", "not-allowed");
                    $("#treeLoadAll").css("cursor", "not-allowed");
                } else {
                    $("#treeLoadMore").css("cursor", "pointer");
                    $("#treeLoadAll").css("cursor", "pointer");
                }

                return treeAll;
            }

            function fmtLHSZdata(res, type) {
                var list = [];
                if(!res) return list;
                var arr = res.split(/[(\r\n)|\n]/g);
                for(var i = arr.length - 1; i >= 0; i--) {
                    if(!arr[i]) arr.splice(i, 1);
                    if(type == "zset" && i == 0) arr.splice(i, 1);
                }
                for(var i = 0, index = 0; i < arr.length; i++) {
                    if(type == "hash" || type == "map" || type == "zset") {
                        if(i % 2 == 0) {
                            list[index] = {
                                id: index,
                                key: arr[i],
                                score: arr[i],
                                value: ""
                            }
                        } else {
                            list[index].value = arr[i];
                            index++;
                        }
                    } else {
                        list[index] = {
                            id: index,
                            value: arr[i]
                        }
                        index++;
                    }
                }
                return list;
            }

            function drawTree(res) { // 渲染tree
                if(!res) {
                    $("#customFile").html("");
                    return;
                }
                for(var key in res) {
                    if(typeof res[key] == "array" || typeof res[key] == "object") {
                        treeHtml += "<div class='customFile-name'><i class='listShow'></i><span>" + key + "</span></div><div class='customFile-list' style='display: none'>";
                        drawTree(res[key])
                    }
                    else treeHtml += "<li>" + res[key] + "</li>";
                }
                treeHtml += "</div>"
                $("#customFile").html(treeHtml);
            }

            function switchRedisContent(type) { // redis切换LHSZ显示
                switch (type) {
                    case "string":
                        redisLHSZ.hide();
                        $("#redisString").show();
                        break;
                    default:
                        redisLHSZ.show();
                        $("#redisString").hide();
                        drawTable(type);
                        break;
                }
                redisTypeName.html(type + " : ");
            }

            function drawTable(type, data) { // 根据redis响应的不同渲染不同的表格
                var headHtml = "<tr>";
                var bodyHtml = "";
                if(data) {
                    for(var i = 0; i < data.length; i++) {
                        bodyHtml += "<tr>";
                        bodyHtml += "<td>" + (i + 1) + "</td>";
                        if(type == "map" || type == "hash") {
                            bodyHtml += "<td>" + data[i].key  + "</td>";
                            bodyHtml += "<td>" + data[i].value + "</td>";
                        } else if(type == "zset") {
                            bodyHtml += "<td>" + data[i].value  + "</td>";
                            bodyHtml += "<td>" + data[i].score + "</td>";
                        } else {
                            bodyHtml += "<td>" + data[i].value + "</td>";
                        }
                        bodyHtml += "<td> <c:if test="${userInfo.type != 2}"> <button class='btn btn-info update' data-index='" + i + "'>修改</button><button class='btn btn-danger del' data-index='" + i + "' data-key='" + data[i].key + "'  data-value='" + data[i].value + "'  data-score='" + data[i].score + "'>删除</button> </c:if> </td>";
                        bodyHtml += "</tr>";
                    }
                }
                for(var i = 0; i < tableTheadOptions[type].length; i++) {
                    headHtml += "<td>" + tableTheadOptions[type][i] + "</td>";
                }
                headHtml += "</tr>";
                redisLHSZ.find("thead").html(headHtml);
                data && redisLHSZ.find("tbody").html(bodyHtml)
            }

            function getCurrKeyDetail () { // 获取树形结构当前点击key的详情(需要反复调用)
                var dos = "";
                var obj = {
                    "string": "GET " + currTreeItemKey,
                    "list": "LRANGE " + currTreeItemKey + " 0 -1",
                    "zset": "ZSCAN " + currTreeItemKey + " 0",
                    "hash": "HGETALL " + currTreeItemKey,
                    "set": "SMEMBERS " + currTreeItemKey
                };
                commands("type " + currTreeItemKey, function(res) {
                    currType = res.result || "";
                    switchRedisContent(res.result);
                    commands(obj[res.result], function(res2) {
                        redisTypeName.next().val(currTreeItemKey);
                        if(res.result == "string") {
                            $("#stringInput").val(res2.result);
                        } else {
                            drawTable(res.result, fmtLHSZdata(res2.result, res.result));
                        }
                    })
                })
                commands("ttl " + currTreeItemKey, function(res) {
                    $("#TTL").val(res.result)
                });
            }

            function updateDialogInput() { // 不同类型对应dialog的title不一样 需要修改
                if(currType == "list" || currType == "set") {
                    $("#dialogInput").hide();
                } else if(currType == "zset") {
                    $("#dialogInput").show().find("p").html("score");
                } else if(currType == "map" || currType == "hash") {
                    $("#dialogInput").show().find("p").html("field");
                }
            }

            $("#customFile").on("click", function(e) { // 树形结构点击监听
                var self = e.target;
                if(self.tagName == "I") {
                    if(self.className.includes("listHide")) $(self).removeClass("listHide").addClass("listShow").parent().next().hide();
                    else $(self).removeClass("listShow").addClass("listHide").parent().next().show();
                } else if(self.tagName == "LI") {
                    currTreeItemKey = $(self).html();
                    getCurrKeyDetail();
                } else if(self.tagName == "SPAN") {
                    if($(self).prev().attr("class").includes("listHide")) $(self).prev().removeClass("listHide").addClass("listShow").parent().next().hide();
                    else $(self).prev().removeClass("listShow").addClass("listHide").parent().next().show();
                }
            });

            $("#stringSave").click(function() { // string类型  保存按钮
                if(!currTreeItemKey) return;
                if(!$("#stringInput").val()) return;
                commands("SET " + currTreeItemKey + " '" + $("#stringInput").val() + "'", function() {
                    msgShow("保存成功");
                });
            });

            $("#saveTTL").click(function(res) { // 保存TTL
                if(!currTreeItemKey) return;
                commands("EXPIRE " + currTreeItemKey + " " + $("#TTL").val(), function() {
                    msgShow();
                })
            });

            $("#delBtn").click(function(res) { // 删除按钮
                commands("DEL " + currTreeItemKey, function() {
                    msgShow("删除成功");
                    refreshTree = true;
                    redisTypeName.next().val("");
                    $("#TTL").val("");
                    drawTable("list", []);
                    $("#stringInput").val("");
                    getTree();
                });
            });

            $("#refreshBtn").click(function() { // 刷新按钮
                getCurrKeyDetail();
            });

            $("#addBtn").click(function() { // 点击添加按钮
                if(!currTreeItemKey) return;
                updateDialogInput();
                $("#formValue").val("");
                $("#dialogInput input").val("");
                $("#editDialog").css({"display": "flex"});
            });

            $("#closeEditDialog").click(function(e) { // 弹框关闭
                $("#editDialog").css({"display": "none"});
            });

            $("#saveEditDialog").click(function(e) { // 弹框数据保存
                var dos = "";
                if(currType == "list") {
                    if(tableCurrIndex >= 0) {
                        dos = "LSET " + currTreeItemKey + " " + tableCurrIndex + " " + $("#formValue").val();
                    } else {
                        dos = "RPUSH " + currTreeItemKey + " " + $("#formValue").val();
                    }
                } else if(currType == "zset") {
                    dos = "ZADD " + currTreeItemKey + " " + $("#dialogInput input").val() + " " + $("#formValue").val();
                    if(tableCurrIndex >= 0) {
                        commands("ZREM "+ currTreeItemKey + " " + currRowValue);
                    }
                } else if(currType == "map" || currType == "hash") {
                    dos = "hset " + currTreeItemKey + " " + $("#dialogInput input").val() + " " + $("#formValue").val();
                    if(tableCurrIndex >= 0) {
                        commands("HDEL " + currTreeItemKey + " " + currRowInput);
                    }
                } else if(currType == "set") {
                    dos = "SADD " + currTreeItemKey + " " + $("#formValue").val();
                    if(tableCurrIndex >= 0) {
                        commands("SREM " + currTreeItemKey + " " + currRowValue);
                    }
                }

                commands(dos, function(res) {
                    getCurrKeyDetail();
                    $("#editDialog").css("display", "none");
                    msgShow("保存成功");
                });
                tableCurrIndex = -1;
            });

            redisLHSZ.on("click", function(e) { // 监听表格按钮操作
                var self = e.target;
                if(self.className.includes("update")) {
                    updateDialogInput();
                    $("#editDialog").css({"display": "flex"});
                    currRowValue = $(self).parent().prev().html();
                    currRowInput = $(self).parent().prev().prev().html();
                    $("#dialogInput input").val(currRowInput);
                    $("#formValue").val(currRowValue);
                    tableCurrIndex = $(self).data("index");
                } else if(self.className.includes("del")) {
                    var obj = {
                        "hash": "hdel " + currTreeItemKey + " '" + $(self).data("key") + "'",
                        "list": "lrem " + currTreeItemKey + " " + $(self).data("index") + " '" + $(self).data("value") + "'",
                        "set": "srem " + currTreeItemKey + " '" + $(self).data("value") + "'",
                        "zset": "zrem " + currTreeItemKey + " '" + $(self).data("value") + "'",
                    }
                    commands(obj[currType], function() {
                        msgShow("删除成功");
                        getCurrKeyDetail();
                    });
                }
            })

            $("#addKeyBtn").click(function() { // 添加key打开dialog
                $("#addKeyDialog").css({"display": "flex"});
            })

            $("#searchTree").click(function() {
                var val = $("input[name='redisKey']").val();
                treeCurrPage = 0;
                refreshTree = true;
                if($("input[name='accurate']").prop("checked")) {
                    getTree("exists " + val, true);
                } else {
                    treeSearchValue = "*" + val + "*";
                    getTree("", true);
                }
            })

            $("#treeLoadMore").click(function() {
                if(treeCurrPage == 0) {
                    return;
                }
                treeCurrSize = 50;
                refreshTree = false;
                getTree();
            });

            $("#treeLoadAll").click(function() {
                if(treeCurrPage == 0) {
                    return;
                }
                refreshTree = false;
                treeCurrSize = 2000;
                getTree();
            });
            
            $("#addKeyCancel").click(function() { // 关闭dialog
                $("#addKeyDialog").hide();
            });

            $("#addKeySave").click(function() { // 新增key保存
                var type = $("#addKeyTypeSelect option:selected").val();
                var key = $("#addKeyValue").val();
                currType = type;
                currTreeItemKey = key;
                var obj = {
                    "string": "SET " + key + " 'new value'",
                    "hash": "HSET " + key + " 'new field'" + " 'new value'",
                    "list": "LPUSH " + key + " 'new value'",
                    "set": "SADD " + key + " 'new value'",
                    "zset": "ZADD " + key + " '0' 'new value'",
                }
                function getKey() {
                    getCurrKeyDetail();
                    refreshTree = false;
                    msgShow("添加成功");
                    getTree();
                }
                commands(obj[type], getKey);
                if(type == "string") {
                    redisTypeName.next().val(key);
                    $("#stringInput").val("new value");
                }
                switchRedisContent(type);
                $("#addKeyDialog").hide();
            });
        })
    })()
</script>